﻿#region [PitchRollControl Using Statements]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using WP7_XNA_Accelerometer_Simulator.GameObjects.SuperClasses;
using WP7_XNA_Accelerometer_Simulator.Utils.GameInfo;
using WP7_XNA_Accelerometer_Simulator.Utils.Accelerometer;
using WP7_XNA_Accelerometer_Simulator.GameObjects.GameModels;
using WP7_XNA_Accelerometer_Simulator.Utils.Controls;
using WP7_XNA_Accelerometer_Simulator.Utils.Intersection;
using WP7_XNA_Accelerometer_Simulator.Utils.Rotation;
#endregion

namespace WP7_XNA_Accelerometer_Simulator.GameObjects.MovementControls
{
    /// <summary>
    /// This Class represents the control responsible for applying 
    /// pitch and roll rotation to the Windows Phone 7
    /// </summary>
    public class PitchRollControl : GameObject3D
    {
        #region [PitchRollControl Fields]
        private List<Model> _pitchRollModel;
        private Model _sphereModel;
        private Model _redKnotModel;
        private Model _greenKnotModel;
        private Model _blueKnotModel;

        private float _xDif;
        private float _yDif;
        private float _sensitivity;
        #endregion

        #region [PitchRollControl Contructor]
        public PitchRollControl()
        {
            Scale = new Vector3(0.015F, 0.015F, 0.015F);
            Position = new Vector3(6, 0, 2);
            _pitchRollModel = new List<Model>();
            _xDif = 0;
            _yDif = 0;
            _sensitivity = 1.7f;
        }
        #endregion

        #region [PitchRollControl LoadContent, Update and Draw Methods]
        public override void LoadContent(ContentManager content)
        {
            _sphereModel = content.Load<Model>(GameConstants.SphereUri);
            _redKnotModel = content.Load<Model>(GameConstants.RedKnotUri);
            _greenKnotModel = content.Load<Model>(GameConstants.GreenKnotUri);
            _blueKnotModel = content.Load<Model>(GameConstants.BlueKnotUri);

            _pitchRollModel.Add(_sphereModel);
            _pitchRollModel.Add(_redKnotModel);
            _pitchRollModel.Add(_greenKnotModel);
            _pitchRollModel.Add(_blueKnotModel);
        }

        public override void Update(GameTime gameTime)
        {
            Ray cursorRay = GameManager.Cursor.CalculateCursorRay(GameManager.CameraProjectionMatrix, GameManager.CameraViewMatrix);

            Matrix[] BonesCountMatrix = new Matrix[_sphereModel.Bones.Count];
            _sphereModel.CopyAbsoluteBoneTransformsTo(BonesCountMatrix);
            Matrix modelPosition = Matrix.CreateTranslation(Position);

            if (GameManager.CurrentMouseState.LeftButton == ButtonState.Pressed &&
                GameManager.PreviousMouseState.LeftButton == ButtonState.Pressed)
            {
                _xDif = GameManager.PreviousMouseState.X - GameManager.CurrentMouseState.X;
                _yDif = GameManager.PreviousMouseState.Y - GameManager.CurrentMouseState.Y;

                /*check intersection*/
                if (Intersection.RayIntersectsModel(cursorRay, _sphereModel, modelPosition, BonesCountMatrix, Scale.X))
                {
                    /*
                     * only apply rotation if the cursor's deslocation is superior to the chosen
                     * sensitivity. This is used to prevent unwanted deslocation in a direction
                     * that is not intended.
                     */

                    if (Math.Abs(_xDif) > _sensitivity)
                    {
                        foreach (GameObject3D gameObject3D in GUI.GameObjects3D)
                        {
                            gameObject3D.ProcessRotation(RotationUtil.RotationType.Roll, _xDif);
                        }
                    }

                    if (Math.Abs(_yDif) > _sensitivity)
                    {
                        foreach (GameObject3D gameObject3D in GUI.GameObjects3D)
                        {
                            gameObject3D.ProcessRotation(RotationUtil.RotationType.Pitch, -_yDif);
                        }
                    }
                }
            }
        }

        public override void Draw(GameTime gameTime)
        {
            //Model gameModel = SphereModel;
            foreach (Model gameModel in _pitchRollModel)
            {
                Matrix[] BonesCountMatrix = new Matrix[gameModel.Bones.Count];
                gameModel.CopyAbsoluteBoneTransformsTo(BonesCountMatrix);
                Matrix modelScale = Matrix.CreateScale(Scale);
                Matrix modelRotation = Matrix.CreateFromQuaternion(QuatRotationMatrix);
                Matrix modelPosition = Matrix.CreateTranslation(Position);

                foreach (ModelMesh mesh in gameModel.Meshes)
                {
                    foreach (BasicEffect effect in mesh.Effects)
                    {
                        effect.EnableDefaultLighting();
                        effect.PreferPerPixelLighting = true;
                        effect.World = BonesCountMatrix[mesh.ParentBone.Index] * modelScale * modelRotation * modelPosition;
                        effect.Projection = GameManager.CameraProjectionMatrix;
                        effect.View = GameManager.CameraViewMatrix;
                    }
                    mesh.Draw();
                }
            }
        }
        #endregion
    }
}

